#include <assert.h>

#include <atomic>
#include <iostream>
#include <thread>
std::atomic<bool> x, y;
std::atomic<int> z;

// write_x_then_y和read_y_then_x各自执行在一个线程中
// x原子变量采用的是relaxed order， y原子变量采用的是acquire-release order
// 两个线程中的y原子存在synchronizes-with的关系，read_y_then_x的load与
// write_x_then_y的y.store存在一种happens-before的关系
// write_x_then_y的y.store执行后能保证read_y_then_x的x.load读到的x一定是true。
// 虽然relaxed并不保证happens-before关系，但是在同一线程里，release会保证在其之前的原子
// store操作都能被看见， acquire能保证同线程中的后续的load都能读到最新值。
// 所以当y.load为true的时候，x肯定可以读到最新值。所以即使这里x用的是relaxed操作，
// 所以其也能达到acquire-release的作用。

void write_x_then_y() {
  x.store(true, std::memory_order_relaxed);  // 1 自旋，等待y被设置为true
  y.store(true, std::memory_order_release);  // 2
}

void read_y_then_x() {
  while (!y.load(std::memory_order_acquire));  // 3
  if (x.load(std::memory_order_relaxed))  // 4
    ++z;
}


int main() {
  x = false;
  y = false;
  z = 0;
  std::thread a(write_x_then_y);
  std::thread b(read_y_then_x);
  a.join();
  b.join();
  assert(z.load() != 0);  // 5

  // 同一个线程 #1->#2， 由于acquire-release， #2->#3 ，又在同一个线程中，
  // #3->#4，所以传递happens-before， #4一定能够获取 #1的值，必然为true。 如果
  // #3的while去掉， #3 可能由于 #2还没有写入数据，导致为false， #4 和 #1
  // 因为relaxed内存序，在不同线程，所以没有排序。release-acquire
  // 对一般配对出现，如果都为release或者acquire，则无法同步。

  std::cout << "----End!------\n";

  return 0;
}